package com.cyy.util


import cn.hutool.cache.impl.TimedCache
import cn.hutool.core.lang.Singleton
import com.jfoenix.controls.JFXDecorator
import javafx.collections.ObservableList
import javafx.event.ActionEvent
import javafx.event.Event
import javafx.event.EventHandler
import javafx.fxml.FXMLLoader
import javafx.scene.Parent
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.control.MenuItem
import javafx.scene.control.*
import javafx.scene.control.SpinnerValueFactory.DoubleSpinnerValueFactory
import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory
import javafx.scene.control.TableColumn.CellEditEvent
import javafx.scene.control.cell.MapValueFactory
import javafx.scene.control.cell.TextFieldListCell
import javafx.scene.control.cell.TextFieldTableCell
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent
import javafx.stage.Modality
import javafx.stage.Screen
import javafx.stage.Stage
import javafx.stage.WindowEvent
import javafx.util.Callback
import javafx.util.StringConverter
import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.reflect.MethodUtils

import java.awt.*
import java.text.DecimalFormat
import java.util.HashMap
import java.util.function.Consumer


object JavaFxViewUtil {

    /**
     * 获取JFoenix面板
     *
     * @param stage
     * @param title   标题
     * @param iconUrl 图标Url
     * @param root    显示的面板
     */
    fun getJFXDecorator(stage: Stage, title: String, iconUrl: String, root: Parent): JFXDecorator {
        val decorator = JFXDecorator(stage, root)
        decorator.isCustomMaximize = true
        decorator.text = title
        if (StringUtils.isNotEmpty(iconUrl)) {
            val imageView = ImageView(Image(iconUrl))
            imageView.fitWidth = 24.0
            imageView.fitHeight = 24.0
            decorator.setGraphic(imageView)
        }
        return decorator
    }

    /**
     * 获取JFoenix窗口
     *
     * @param stage
     * @param title   标题
     * @param iconUrl 图标Url
     * @param root    显示的面板
     */
    fun getJFXDecoratorScene(stage: Stage, title: String, iconUrl: String, root: Parent): Scene {
        val decorator = getJFXDecorator(stage, title, iconUrl, root)
        return getJFXDecoratorScene(decorator)
    }

    /**
     * 获取JFoenix窗口
     *
     * @param decorator 显示的decorator面板
     */
    fun getJFXDecoratorScene(decorator: JFXDecorator): Scene {
        val screenSize = Toolkit.getDefaultToolkit().screenSize
        var width = screenSize.width / 1.35
        var height = screenSize.height / 1.2
        val bounds = Screen.getPrimary().visualBounds
        if (width > bounds.width || height > bounds.height) {//解决屏幕缩放问题
            width = bounds.width
            height = bounds.height
        }
        val scene = Scene(decorator, width, height)
        val stylesheets = scene.stylesheets
        stylesheets.addAll(
                //                JavaFxViewUtil.class.getResource("/css/jfoenix-fonts.css").toExternalForm(),
                //                JavaFxViewUtil.class.getResource("/css/jfoenix-design.css").toExternalForm(),
                JavaFxViewUtil::class.java.getResource("/css/jfoenix-main.css").toExternalForm())
        return scene
    }

    /*
     * 获取新窗口
     */
    fun getNewStage(title: String, iconUrl: String, root: Parent): Stage {
        var iconUrl = iconUrl
        val newStage = Stage()
        newStage.title = title
        newStage.initModality(Modality.NONE)
        newStage.isResizable = true//可调整大小

        if (StringUtils.isEmpty(iconUrl)) {
            iconUrl = "/images/icon.jpg"
        }
        val scene = JavaFxViewUtil.getJFXDecoratorScene(newStage, title, iconUrl, root)
        newStage.scene = scene
        //        newStage.setScene(new Scene(root));
        //		newStage.setMaximized(false);
        newStage.icons.add(Image(iconUrl))
        newStage.show()
        return newStage
    }

    /*
     * 获取新窗口，并添加关闭回调事件
     */
    fun getNewStage(title: String, iconUrl: String, fXMLLoader: FXMLLoader): Stage? {
        var newStage: Stage? = null
        try {
            newStage = getNewStage(title, iconUrl, fXMLLoader.load<Parent>())
            newStage.setOnCloseRequest { event: WindowEvent -> setControllerOnCloseRequest(fXMLLoader.getController(), event) }
        } catch (e: Exception) {
            Error("加载新窗口失败", e)
        }

        return newStage
    }

    //打开一个等待窗口
    fun openNewWindow(title: String, root: Parent) {
        val window = Stage()
        window.title = title
        window.initModality(Modality.APPLICATION_MODAL)
        val scene = Scene(root)
        window.scene = scene
        window.showAndWait()
    }

    //设置窗口移除前回调
    fun setControllerOnCloseRequest(controller: Any, event: Event) {
        try {
            val method = MethodUtils.getAccessibleMethod(controller.javaClass, "onCloseRequest", Event::class.java)
            if (method != null) {
                MethodUtils.invokeMethod(controller, "onCloseRequest", event)
            }
        } catch (e: Exception) {
            Error("执行onCloseRequest方法失败", e)
        }
    }

    /**
     * 设置Spinner最大最小值
     */
//    fun setSpinnerValueFactory(spinner: Spinner<Int>, min: Int, max: Int) {
//        setSpinnerValueFactory(spinner, min, max, min, 1)
//    }
//
//    fun setSpinnerValueFactory(spinner: Spinner<Int>, min: Int, max: Int, initialValue: Int) {
//        setSpinnerValueFactory(spinner, min, max, initialValue, 1)
//    }
//
//    fun setSpinnerValueFactory(spinner: Spinner<Double>, min: Double, max: Double) {
//        setSpinnerValueFactory(spinner, min, max, min, 1.0)
//    }

//    fun setSpinnerValueFactory(spinner: Spinner<Double>, min: Double, max: Double, initialValue: Double) {
//        setSpinnerValueFactory(spinner, min, max, initialValue, 1.0)
//    }
//
//    fun setSpinnerValueFactory(spinner: Spinner<*>, min: Number, max: Number, initialValue: Number, amountToStepBy: Number) {
//        if (min is Int) {
//            val secondStart_0svf = IntegerSpinnerValueFactory(min, max.toInt(), initialValue.toInt(), amountToStepBy.toInt())
//            spinner.valueFactory=secondStart_0svf
//            spinner.editor.textProperty().addListener { _, oldValue, newValue ->
//                try {
//                    spinner.valueFactory.value=newValue.toInt()
//                } catch (e: Exception) {
////                    log.warn("数字int转换异常 newValue:$newValue")
//                    spinner.editor.text = oldValue
//                }
//            }
//        } else if (min is Double) {
//            val secondStart_0svf = DoubleSpinnerValueFactory(min, max as Double, initialValue as Double, amountToStepBy as Double)
//            spinner.valueFactory=secondStart_0svf
//            spinner.editor.textProperty().addListener { _, oldValue, newValue ->
//                try {
//                    spinner.valueFactory.setValue(newValue.toDouble())
//                } catch (e: Exception) {
////                    log.warn("数字double转换异常 newValue:$newValue")
//                    spinner.editor.text = oldValue
//                }
//            }
//        }
//    }

    /**
     * @Title: setSliderLabelFormatter
     * @Description: 格式化Slider显示内容
     */
    fun setSliderLabelFormatter(slider: Slider, formatter: String) {
        slider.labelFormatter = object : StringConverter<Double>() {
            override fun toString(`object`: Double?): String {
                val decimalFormat = DecimalFormat(formatter)
                return decimalFormat.format(`object`)
            }

            override fun fromString(string: String): Double? {
                return java.lang.Double.valueOf(string)
            }
        }
    }

    /**
     * @Title: addTableViewOnMouseRightClickMenu
     * @Description: 添加TableView右键菜单
     */
    fun addTableViewOnMouseRightClickMenu(tableView: TableView<Map<String, String>>) {
        tableView.isEditable = true
        tableView.setOnMouseClicked { event ->
            if (event.button == MouseButton.SECONDARY) {
                val menuAdd = MenuItem("添加行")
                menuAdd.setOnAction { event1 -> tableView.items.add(HashMap()) }
                val menu_Copy = MenuItem("复制选中行")
                menu_Copy.setOnAction { event1 ->
                    val map = tableView.selectionModel.selectedItem
                    val map2 = HashMap(map)
                    tableView.items.add(tableView.selectionModel.selectedIndex, map2)
                }
                val menu_Remove = MenuItem("删除选中行")
                menu_Remove.setOnAction { event1 -> tableView.items.removeAt(tableView.selectionModel.selectedIndex) }
                val menu_RemoveAll = MenuItem("删除所有")
                menu_RemoveAll.setOnAction { event1 -> tableView.items.clear() }
                tableView.contextMenu = ContextMenu(menuAdd, menu_Copy, menu_Remove, menu_RemoveAll)
            }
        }
    }

    /**
     * @Title: addListViewOnMouseRightClickMenu
     * @Description: 添加ListView右键菜单
     */
    fun addListViewOnMouseRightClickMenu(listView: ListView<String>) {
        listView.isEditable = true
        listView.setCellFactory(TextFieldListCell.forListView())
        listView.setOnMouseClicked { event ->
            if (event.button == MouseButton.SECONDARY) {
                val menuAdd = MenuItem("添加行")
                menuAdd.setOnAction { event1 -> listView.items.add("") }
                val menu_Copy = MenuItem("复制选中行")
                menu_Copy.setOnAction { event1 -> listView.items.add(listView.selectionModel.selectedIndex, listView.selectionModel.selectedItem) }
                val menu_Remove = MenuItem("删除选中行")
                menu_Remove.setOnAction { event1 -> listView.items.removeAt(listView.selectionModel.selectedIndex) }
                val menu_RemoveAll = MenuItem("删除所有")
                menu_RemoveAll.setOnAction { event1 -> listView.items.clear() }
                listView.contextMenu = ContextMenu(menuAdd, menu_Copy, menu_Remove, menu_RemoveAll)
            }
        }
    }

    /**
     * @Title: setSpinnerValueFactory
     * @Description: 初始化表格属性
     */
//    fun setTableColumnMapValueFactory(tableColumn: TableColumn<*, *>, name: String) {
//        setTableColumnMapValueFactory(tableColumn, name, true, null)
//    }

//    @JvmOverloads
//    fun setTableColumnMapValueFactory(tableColumn: TableColumn<*, *>, name: String, isEdit: Boolean, onEditCommitHandle: Runnable? = null) {
//        tableColumn.cellValueFactory = MapValueFactory(name)
//        tableColumn.cellFactory = TextFieldTableCell.forTableColumn<Map<String, String>>()
//        if (isEdit) {
//            tableColumn.onEditCommit = EventHandler<CellEditEvent<Map<String, String>, String>> { t ->
//                t.rowValue.plus(name to t.newValue)
//                onEditCommitHandle?.run()
//            }
//        }
//    }

    fun setTableColumnButonFactory(tableColumn: TableColumn<*, *>, name: String, value: EventHandler<in MouseEvent>) {
        setTableColumnButonFactory(tableColumn, name,value)
    }

    fun setTableColumnButonFactory(tableColumn: TableColumn<*, *>, name: String, mouseEventCallFunc: MouseEventCallFunc) {
        tableColumn.cellFactory = MyTableCell(name, mouseEventCallFunc)
    }



    /**
     * @Title: setTableColumnMapValueFactoryAsChoiceBox
     * @Description: 初始化下拉选择表格属性
     */
//    fun setTableColumnMapAsChoiceBoxValueFactory(tableColumn: TableColumn<*, *>, name: String, choiceBoxStrings: Array<String>) {
//        tableColumn.cellValueFactory=MapValueFactory(name)
//        tableColumn.cellFactory=Callback<TableColumn<Map<String, String>, String>, TableCell<Map<String, String>, String>> {
//                    object : TableCell<Map<String, String>, String>() {
//                        override fun updateItem(item: String, empty: Boolean) {
//                            super.updateItem(item, empty)
//                            text = null
//                            graphic = null
//                            if (!empty) {
//                                val tableData = tableColumn.tableView.items as ObservableList<Map<String, String>>
//                                val choiceBox = ChoiceBox<String>()
//                                choiceBox.items.addAll(*choiceBoxStrings)
//                                choiceBox.setValue(tableData[index][name])
//                                choiceBox.valueProperty().addListener { _, _, newVal -> tableData[index].plus(name to newVal) }
//                                graphic = choiceBox
//                            }
//                        }
//                    }
//                }
//    }
//
//    /**
//     * 初始化选择框表格属性
//     */
//    fun setTableColumnMapAsCheckBoxValueFactory(tableColumn: TableColumn<*, *>, name: String) {
//        tableColumn.cellValueFactory=MapValueFactory(name)
//        tableColumn.cellFactory=Callback<TableColumn<Map<String, String>, String>, TableCell<Map<String, String>, String>> {
//                    object : TableCell<Map<String, String>, String>() {
//                        override fun updateItem(item: String, empty: Boolean) {
//                            super.updateItem(item, empty)
//                            text = null
//                            graphic = null
//                            if (!empty) {
//                                val tableData = tableColumn.tableView.items  as ObservableList<Map<String, String>>
//                                val checkBox = CheckBox()
//                                checkBox.isSelected = java.lang.Boolean.valueOf(tableData[index][name] as Boolean)
//                                checkBox.selectedProperty().addListener { _, _, newVal -> tableData[index].plus(name to newVal) }
//                                graphic = checkBox
//                            }
//                        }
//                    }
//                }
//    }

    /**
     * 设置改变事件监听操作
     */
    fun setPropertyAddChangeListener(inputControl: TextInputControl, consumer: Consumer<ActionEvent>) {
        inputControl.textProperty().addListener { _, _, _ ->
            Singleton.get(TimedCache::class.java, 2000.toLong()).apply {
                if(this.contains<Any?>("initiativeChange")) return@apply
                put("initiativeChange" as Nothing?, true as Nothing?)
//                consumer.accept(inputControl.text)
                remove("initiativeChange" as Nothing?)
            }
        }
    }

    /**
     * 设置改变事件监听操作
     */
    fun setPropertyAddChangeListener(inputControl: TextInputControl, runnable: Runnable) {
        inputControl.textProperty().addListener { observable, oldValue, newValue -> setPropertyChangeRun(runnable) }
    }

    /**
     * 设置改变事件监听防重复操作
     */
    fun setPropertyChangeRun(runnable: Runnable) {
        Singleton.get(TimedCache::class.java, 2000.toLong()).apply {
            if(this.contains<Any?>("initiativeChange")) return@apply
            put("initiativeChange" as Nothing?, true as Nothing?)
            runnable.run()
            remove("initiativeChange" as Nothing?)
        }
    }
}

interface MouseEventCallFunc {
    fun callFun(mouseEvent: MouseEvent, index: Int?)
}

class MyTableCell(var name: String, var mouseEventCallFunc: MouseEventCallFunc) : TableCell<Any, Boolean>(), Callback<TableColumn<out Any, out Any>, TableCell<out Any, out Any>> {
    override fun call(param: TableColumn<out Any, out Any>?): TableCell<out Any, out Any> {
        return this
    }

    public override fun updateItem(item: Boolean?, empty: Boolean) {
        super.updateItem(item, empty)
        this.text = null
        this.graphic = null
        if (!empty) {
            val delBtn = Button(name)
            this.contentDisplay = ContentDisplay.CENTER
            this.graphic = delBtn
            delBtn.setOnMouseClicked { me -> mouseEventCallFunc.callFun(me, this.index) }
        }
    }
}